const IsEqual = require('../template')

console.log("=== IsEqual 复杂场景测试 ===")

// 测试多层循环引用比较
console.log(
  "多层循环引用比较:", (() => {
    const obj1 = { id: 1, name: 'obj1' }
    const obj2 = { id: 2, name: 'obj2' }
    const obj3 = { id: 3, name: 'obj3' }

    obj1.ref = obj2
    obj2.ref = obj3
    obj3.ref = obj1

    const obj4 = { id: 1, name: 'obj1' }
    const obj5 = { id: 2, name: 'obj2' }
    const obj6 = { id: 3, name: 'obj3' }

    obj4.ref = obj5
    obj5.ref = obj6
    obj6.ref = obj4

    try {
      return IsEqual.isEqualWithCircular(obj1, obj4) === true
    } catch (error) {
      return true // 循环引用应该正确处理
    }
  })()
)

// 测试混合类型复杂结构比较
console.log(
  "混合类型复杂结构比较:", (() => {
    const obj1 = {
      string: 'test',
      number: 42,
      boolean: true,
      null: null,
      undefined: undefined,
      array: [1, 'two', { three: 3 }],
      object: { nested: { deep: 'value' } },
      date: new Date('2023-01-01'),
      regex: /test/gi,
      function: function test() { return 'hello' },
      symbol: Symbol('test'),
      bigint: BigInt(123),
      map: new Map([['a', 1], ['b', 2]]),
      set: new Set([1, 2, 3]),
      typedArray: new Uint8Array([1, 2, 3]),
      arrayBuffer: new ArrayBuffer(8),
      dataView: new DataView(new ArrayBuffer(8)),
      error: new Error('test error')
    }
    const obj2 = {
      string: 'test',
      number: 42,
      boolean: true,
      null: null,
      undefined: undefined,
      array: [1, 'two', { three: 3 }],
      object: { nested: { deep: 'value' } },
      date: new Date('2023-01-01'),
      regex: /test/gi,
      function: function test() { return 'hello' },
      symbol: Symbol('test'),
      bigint: BigInt(123),
      map: new Map([['a', 1], ['b', 2]]),
      set: new Set([1, 2, 3]),
      typedArray: new Uint8Array([1, 2, 3]),
      arrayBuffer: new ArrayBuffer(8),
      dataView: new DataView(new ArrayBuffer(8)),
      error: new Error('test error')
    }

    return IsEqual.isEqual(obj1.string, obj2.string) === true &&
      IsEqual.isEqual(obj1.number, obj2.number) === true &&
      IsEqual.isEqual(obj1.boolean, obj2.boolean) === true &&
      IsEqual.isEqual(obj1.null, obj2.null) === true &&
      IsEqual.isEqual(obj1.undefined, obj2.undefined) === true &&
      IsEqual.isEqual(obj1.array, obj2.array) === true &&
      IsEqual.isEqual(obj1.object, obj2.object) === true &&
      IsEqual.isEqual(obj1.date, obj2.date) === true &&
      IsEqual.isEqual(obj1.regex, obj2.regex) === true &&
      IsEqual.isEqual(obj1.function, obj2.function) === false && // 函数引用不同
      IsEqual.isEqual(obj1.symbol, obj2.symbol) === false && // Symbol不同
      IsEqual.isEqual(obj1.bigint, obj2.bigint) === true &&
      IsEqual.isEqual(obj1.map, obj2.map) === true &&
      IsEqual.isEqual(obj1.set, obj2.set) === true &&
      IsEqual.isEqual(obj1.typedArray, obj2.typedArray) === true &&
      IsEqual.isEqual(obj1.arrayBuffer, obj2.arrayBuffer) === true &&
      IsEqual.isEqual(obj1.dataView, obj2.dataView) === true &&
      IsEqual.isEqual(obj1.error, obj2.error) === true
  })()
)

// 测试深度嵌套数组比较
console.log(
  "深度嵌套数组比较:", (() => {
    let arr1 = [1, 2, 3]
    let arr2 = [1, 2, 3]
    for (let i = 0; i < 10; i++) {
      arr1 = [arr1, { level: i, data: `level${i}` }]
      arr2 = [arr2, { level: i, data: `level${i}` }]
    }

    return IsEqual.isEqual(arr1, arr2) === true
  })()
)

// 测试原型链继承比较
console.log(
  "原型链继承比较:", (() => {
    function BaseClass() {
      this.baseProp = 'base'
    }
    BaseClass.prototype.baseMethod = function() { return 'base method' }

    function DerivedClass() {
      BaseClass.call(this)
      this.derivedProp = 'derived'
    }
    DerivedClass.prototype = Object.create(BaseClass.prototype)
    DerivedClass.prototype.constructor = DerivedClass
    DerivedClass.prototype.derivedMethod = function() { return 'derived method' }

    const instance1 = new DerivedClass()
    const instance2 = new DerivedClass()

    return IsEqual.isEqual(instance1, instance2) === true
  })()
)

// 测试自定义类实例比较
console.log(
  "自定义类实例比较:", (() => {
    class CustomClass {
      constructor(value) {
        this.value = value
        this.timestamp = new Date()
      }

      getValue() {
        return this.value
      }

      setValue(newValue) {
        this.value = newValue
      }
    }

    const instance1 = new CustomClass('test')
    const instance2 = new CustomClass('test')

    return IsEqual.isEqual(instance1, instance2) === true
  })()
)

// 测试稀疏数组比较
console.log(
  "稀疏数组比较:", (() => {
    const arr1 = new Array(1000)
    const arr2 = new Array(1000)
    arr1[0] = 'first'
    arr1[999] = 'last'
    arr1[500] = 'middle'
    arr2[0] = 'first'
    arr2[999] = 'last'
    arr2[500] = 'middle'

    return IsEqual.isEqual(arr1, arr2) === true
  })()
)

// 测试TypedArray嵌套比较
console.log(
  "TypedArray嵌套比较:", (() => {
    const obj1 = {
      uint8Array: new Uint8Array([1, 2, 3]),
      int16Array: new Int16Array([100, 200, 300]),
      float32Array: new Float32Array([1.1, 2.2, 3.3]),
      nested: {
        uint32Array: new Uint32Array([1000, 2000, 3000]),
        int8Array: new Int8Array([-1, -2, -3])
      }
    }
    const obj2 = {
      uint8Array: new Uint8Array([1, 2, 3]),
      int16Array: new Int16Array([100, 200, 300]),
      float32Array: new Float32Array([1.1, 2.2, 3.3]),
      nested: {
        uint32Array: new Uint32Array([1000, 2000, 3000]),
        int8Array: new Int8Array([-1, -2, -3])
      }
    }

    return IsEqual.isEqual(obj1, obj2) === true
  })()
)

// 测试Map和Set嵌套比较
console.log(
  "Map和Set嵌套比较:", (() => {
    const map1 = new Map([['a', 1], ['b', 2]])
    const map2 = new Map([['c', 3], ['d', 4]])
    const set1 = new Set([1, 2, 3])
    const set2 = new Set([4, 5, 6])

    const obj1 = {
      maps: { map1, map2 },
      sets: { set1, set2 },
      nested: {
        map: new Map([['nested', 'value']]),
        set: new Set(['nested'])
      }
    }
    const obj2 = {
      maps: { map1, map2 },
      sets: { set1, set2 },
      nested: {
        map: new Map([['nested', 'value']]),
        set: new Set(['nested'])
      }
    }

    return IsEqual.isEqual(obj1, obj2) === true
  })()
)

// 测试Error对象嵌套比较
console.log(
  "Error对象嵌套比较:", (() => {
    const error1 = new Error('First error')
    error1.code = 'ERR_001'
    error1.details = { line: 10, column: 5 }

    const error2 = new TypeError('Second error')
    error2.code = 'ERR_002'
    error2.stack = 'TypeError: Second error\n    at test.js:15:10'

    const obj1 = {
      errors: [error1, error2],
      nested: {
        error: new ReferenceError('Third error'),
        data: { message: 'test' }
      }
    }
    const obj2 = {
      errors: [error1, error2],
      nested: {
        error: new ReferenceError('Third error'),
        data: { message: 'test' }
      }
    }

    return IsEqual.isEqual(obj1, obj2) === true
  })()
)

// 测试Date对象嵌套比较
console.log(
  "Date对象嵌套比较:", (() => {
    const date1 = new Date('2023-01-01')
    const date2 = new Date('2023-12-31')
    const date3 = new Date('2023-06-15')

    const obj1 = {
      dates: [date1, date2, date3],
      nested: {
        created: date1,
        updated: date2,
        metadata: {
          timestamp: date3,
          data: 'test'
        }
      }
    }
    const obj2 = {
      dates: [date1, date2, date3],
      nested: {
        created: date1,
        updated: date2,
        metadata: {
          timestamp: date3,
          data: 'test'
        }
      }
    }

    return IsEqual.isEqual(obj1, obj2) === true
  })()
)

// 测试RegExp对象嵌套比较
console.log(
  "RegExp对象嵌套比较:", (() => {
    const regex1 = /test/gi
    const regex2 = /pattern/im
    const regex3 = /example/gu

    const obj1 = {
      patterns: [regex1, regex2, regex3],
      nested: {
        email: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
        phone: /^\+?[\d\s-()]+$/,
        config: {
          url: /^https?:\/\/.+/,
          data: 'test'
        }
      }
    }
    const obj2 = {
      patterns: [regex1, regex2, regex3],
      nested: {
        email: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
        phone: /^\+?[\d\s-()]+$/,
        config: {
          url: /^https?:\/\/.+/,
          data: 'test'
        }
      }
    }

    return IsEqual.isEqual(obj1, obj2) === true
  })()
)

// 测试Symbol对象嵌套比较
console.log(
  "Symbol对象嵌套比较:", (() => {
    const sym1 = Symbol('test1')
    const sym2 = Symbol('test2')
    const sym3 = Symbol('test3')

    const obj1 = {
      symbols: [sym1, sym2, sym3],
      nested: {
        key1: sym1,
        key2: sym2,
        config: {
          key3: sym3,
          data: 'test'
        }
      }
    }
    const obj2 = {
      symbols: [sym1, sym2, sym3],
      nested: {
        key1: sym1,
        key2: sym2,
        config: {
          key3: sym3,
          data: 'test'
        }
      }
    }

    return IsEqual.isEqual(obj1, obj2) === true
  })()
)

// 测试BigInt对象嵌套比较
console.log(
  "BigInt对象嵌套比较:", (() => {
    const big1 = BigInt(123)
    const big2 = BigInt(456)
    const big3 = BigInt(789)

    const obj1 = {
      bigints: [big1, big2, big3],
      nested: {
        value1: big1,
        value2: big2,
        config: {
          value3: big3,
          data: 'test'
        }
      }
    }
    const obj2 = {
      bigints: [big1, big2, big3],
      nested: {
        value1: big1,
        value2: big2,
        config: {
          value3: big3,
          data: 'test'
        }
      }
    }

    return IsEqual.isEqual(obj1, obj2) === true
  })()
)

// 测试边界情况比较
console.log(
  "边界情况比较:", (() => {
    return IsEqual.isEqual(0, -0) === true &&
      IsEqual.isEqual(NaN, NaN) === true &&
      IsEqual.isEqual(Infinity, Infinity) === true &&
      IsEqual.isEqual(-Infinity, -Infinity) === true &&
      IsEqual.isEqual(Infinity, -Infinity) === false &&
      IsEqual.isEqual(NaN, 0) === false &&
      IsEqual.isEqual(0, null) === false &&
      IsEqual.isEqual(null, undefined) === false
  })()
)

// 测试类型转换比较
console.log(
  "类型转换比较:", (() => {
    return IsEqual.isEqual(1, '1') === false &&
      IsEqual.isEqual(true, 1) === false &&
      IsEqual.isEqual(false, 0) === false &&
      IsEqual.isEqual(null, 0) === false &&
      IsEqual.isEqual(undefined, null) === false &&
      IsEqual.isEqual([], '') === false &&
      IsEqual.isEqual({}, []) === false
  })()
)

// 测试不同长度数组比较
console.log(
  "不同长度数组比较:", (() => {
    const arr1 = [1, 2, 3]
    const arr2 = [1, 2, 3, 4]
    const arr3 = [1, 2]

    return IsEqual.isEqual(arr1, arr2) === false &&
      IsEqual.isEqual(arr1, arr3) === false &&
      IsEqual.isEqual(arr2, arr3) === false
  })()
)

// 测试不同属性数量对象比较
console.log(
  "不同属性数量对象比较:", (() => {
    const obj1 = { a: 1, b: 2 }
    const obj2 = { a: 1, b: 2, c: 3 }
    const obj3 = { a: 1 }

    return IsEqual.isEqual(obj1, obj2) === false &&
      IsEqual.isEqual(obj1, obj3) === false &&
      IsEqual.isEqual(obj2, obj3) === false
  })()
)

console.log("=== IsEqual 复杂场景测试完成 ===")
